package org.dding.msc.service.impl;

import java.util.Collection;
import java.util.HashSet;

import org.dding.msc.exception.ServiceRegistryException;
import org.dding.msc.service.BatchServiceTarget;
import org.dding.msc.service.Service;
import org.dding.msc.service.ServiceBuilder;
import org.dding.msc.service.ServiceController;
import org.dding.msc.service.ServiceListener;
import org.dding.msc.service.ServiceName;
import org.dding.msc.value.ImmediateValue;

/**
 * {@link BatchServiceTarget} implementation.
 * 
 */
class BatchServiceTargetImpl extends ServiceTargetImpl implements
		BatchServiceTarget {

	private final Collection<ServiceController<?>> addedServiceControllers;

	BatchServiceTargetImpl(final ServiceTargetImpl parent) {
		super(parent);
		addedServiceControllers = new HashSet<ServiceController<?>>();
	}

	@Override
	public void removeServices() {
		final Collection<ServiceController<?>> controllers = addedServiceControllers;
		synchronized (controllers) {
			for (ServiceController<?> serviceController : controllers) {
				if (serviceController != null) {
					serviceController.setMode(ServiceController.Mode.REMOVE);
				}
			}
			controllers.clear();
		}
	}

	<T> ServiceController<T> install(final ServiceBuilderImpl<T> serviceBuilder)
			throws ServiceRegistryException {
		final ServiceController<T> controller = super.install(serviceBuilder);
		final Collection<ServiceController<?>> controllers = addedServiceControllers;
		synchronized (controllers) {
			controllers.add(controller);
		}
		return controller;
	}

	@Override
	public <T> ServiceBuilder<T> addService(ServiceName name, Service<T> service) {
		return addServiceValue(name, new ImmediateValue<Service<T>>(service));
	}

	// these are overridden for covariant return type only

	public BatchServiceTarget addListener(final ServiceListener<Object> listener) {
		super.addListener(listener);
		return this;
	}

	public BatchServiceTarget addListener(
			final ServiceListener<Object>... listeners) {
		super.addListener(listeners);
		return this;
	}

	public BatchServiceTarget addListener(
			final Collection<ServiceListener<Object>> listeners) {
		super.addListener(listeners);
		return this;
	}

	public BatchServiceTarget removeListener(
			final ServiceListener<Object> listener) {
		super.removeListener(listener);
		return this;
	}
}
